with ada.Strings.Fixed; use ada.Strings.Fixed;
with ada.Unchecked_Deallocation;

package body ariane.maths.matrix.utility is


  -- returns the string representation of the give matrix;
  function tostring(m : imatrix.object'class) return string is
    type tmpstr_t is access string;
    tmpstr  : tmpstr_t;
    tmpstr2 : tmpstr_t;
    incstep : constant positive := 256;
    shortfall : positive;
    -- appx number of numbers expected to fit by inc
    incexpt : constant positive := 32;
    incsize : positive;
    allowance : constant positive := 16;
    cursize : positive := incstep;
    currpos : positive := 1;

    procedure free is new Ada.Unchecked_Deallocation
      (Object=> string, Name => tmpstr_t);

    procedure strcpy(source : string; len : positive; target : out string) is
    begin
      for i in 1..len loop
        target(i) := source(i);
      end loop;
    end strcpy;

    procedure append(s : string) is
    begin
      if currpos + s'Length > cursize then
        shortfall := currpos + s'length + allowance - cursize;
        incsize := (shortfall * incexpt + incstep - 1) / incstep;
        incsize := incsize * incstep;
        cursize := cursize + incsize;
        tmpstr2 := new string(1..cursize);
        strcpy(tmpstr.all, currpos-1, tmpstr2.all);
        free(tmpstr);
        tmpstr := tmpstr2;
      end if;
      overwrite(tmpstr.all, currpos, s);
      currpos := currpos + s'Length;
    end append;

  begin
    tmpstr := new string(1..cursize);
    append("(");
    for i in 1..m.numrows loop
      append("(");
      for j in 1..m.numcols loop
        declare
          s : string := tostring(m.get(i,j));
        begin
          append(s);
          if j < m.numcols then
            append(",");
          end if;
        end;
      end loop;
      append(")");
      if i < m.numrows then
        append(";");
      end if;
    end loop;
    append(")");

    declare
      result : string(1..currpos-1);
    begin
      strcpy(tmpstr.all, currpos-1, result);
      free(tmpstr);
      return result;
    end;
  end tostring;

end ariane.maths.matrix.utility;
